home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / pibcat.zip / PIBCATS1.PAS < prev    next >
Pascal/Delphi Source File  |  1989-03-31  |  36KB  |  700 lines

  1. (*--------------------------------------------------------------------------*)
  2. (*               Trim --- Trim trailing blanks from a string                *)
  3. (*--------------------------------------------------------------------------*)
  4.  
  5. FUNCTION Trim( S : AnyStr ) : AnyStr;
  6.  
  7. (*--------------------------------------------------------------------------*)
  8. (*                                                                          *)
  9. (*     Function:   Trim                                                     *)
  10. (*                                                                          *)
  11. (*     Purpose:    Trims trailing blanks from a string                      *)
  12. (*                                                                          *)
  13. (*     Calling sequence:                                                    *)
  14. (*                                                                          *)
  15. (*         Trimmed_S := TRIM( S );                                          *)
  16. (*                                                                          *)
  17. (*            S          --- the string to be trimmed                       *)
  18. (*            Trimmed_S  --- the trimmed version of S                       *)
  19. (*                                                                          *)
  20. (*     Calls:  None                                                         *)
  21. (*                                                                          *)
  22. (*     Remarks:                                                             *)
  23. (*                                                                          *)
  24. (*        Note that the original string itself is left untrimmed.           *)
  25. (*                                                                          *)
  26. (*     Pascal version might be written as:                                  *)
  27. (*                                                                          *)
  28. (*        VAR                                                               *)
  29. (*           I:       INTEGER;                                              *)
  30. (*                                                                          *)
  31. (*        BEGIN                                                             *)
  32. (*                                                                          *)
  33. (*           I := ORD( S[0] );                                              *)
  34. (*                                                                          *)
  35. (*           WHILE ( I > 0 ) AND ( S[I] = ' ' ) DO                          *)
  36. (*              I := PRED( I );                                             *)
  37. (*                                                                          *)
  38. (*           S[0] := CHR( I );                                              *)
  39. (*           Trim := S;                                                     *)
  40. (*                                                                          *)
  41. (*        END;                                                              *)
  42. (*                                                                          *)
  43. (*--------------------------------------------------------------------------*)
  44.  
  45. BEGIN (* Trim *)
  46.  
  47. INLINE(
  48.   $1E/                   {         PUSH    DS                ; Save DS}
  49.                          {;}
  50.   $C5/$76/$06/           {         LDS     SI,[BP+6]         ; Get address of S}
  51.   $FC/                   {         CLD                       ; Forward search}
  52.   $AC/                   {         LODSB                     ; Get length of S}
  53.   $3C/$00/               {         CMP     AL,0              ; See if length 0}
  54.   $74/$21/               {         JE      Trim2             ; If so, no trimming required}
  55.                          {;}
  56.   $30/$ED/               {         XOR     CH,CH}
  57.   $88/$C1/               {         MOV     CL,AL             ; Remember length for search loop}
  58.                          {;}
  59.   $B0/$20/               {         MOV     AL,' '            ; Blank to AL}
  60.                          {;}
  61.   $C4/$7E/$06/           {         LES     DI,[BP+6]         ; Get address of S}
  62.   $01/$CF/               {         ADD     DI,CX             ; Point to end of source string}
  63.                          {;}
  64.   $FD/                   {         STD                       ; Backwards search}
  65.   $F3/$AE/               {         REPE    SCASB             ; Scan over blanks}
  66.   $74/$01/               {         JE      Trim1             ; If CX=0, entire string is blank.}
  67.   $41/                   {         INC     CX}
  68.                          {;}
  69.   $88/$C8/               {Trim1:   MOV     AL,CL             ; Length to copy}
  70.   $C5/$76/$06/           {         LDS     SI,[BP+6]         ; Source string address}
  71.   $46/                   {         INC     SI                ; Skip length}
  72.   $C4/$7E/$0A/           {         LES     DI,[BP+10]        ; Result string address}
  73.   $FC/                   {         CLD                       ; Forward move}
  74.   $AA/                   {         STOSB                     ; Set length in result}
  75.   $F2/$A4/               {         REP     MOVSB             ; Move trimmed result}
  76.   $E9/$04/$00/           {         JMP     Exit}
  77.                          {;}
  78.   $C4/$7E/$0A/           {Trim2:   LES     DI,[BP+10]        ; Result string address}
  79.   $AA/                   {         STOSB                     ; Set length=0 in result}
  80.                          {;}
  81.   $1F);                  {Exit:    POP     DS                ; Restore DS}
  82.  
  83. END   (* Trim *);
  84.  
  85. (*--------------------------------------------------------------------------*)
  86. (*                     Dupl -- Duplicate a character n times                *)
  87. (*--------------------------------------------------------------------------*)
  88.  
  89. FUNCTION Dupl( Dup_char : Char; Dup_Count: INTEGER ) : AnyStr;
  90.  
  91. (*--------------------------------------------------------------------------*)
  92. (*                                                                          *)
  93. (*    Function: Dupl                                                        *)
  94. (*                                                                          *)
  95. (*    Purpose:  Duplicate a character n times                               *)
  96. (*                                                                          *)
  97. (*    Calling Sequence:                                                     *)
  98. (*                                                                          *)
  99. (*       Dup_String := Dupl( Dup_Char: Char; Dup_Count: INTEGER ): AnyStr;  *)
  100. (*                                                                          *)
  101. (*          Dup_Char   --- Character to be duplicated                       *)
  102. (*          Dup_Count  --- Number of times to duplicate character           *)
  103. (*          Dup_String --- Resultant duplicated string                      *)
  104. (*                                                                          *)
  105. (*    Calls:  None                                                          *)
  106. (*                                                                          *)
  107. (*    Remarks:                                                              *)
  108. (*                                                                          *)
  109. (*       This routine could be programmed directly in Turbo as:             *)
  110. (*                                                                          *)
  111. (*          VAR                                                             *)
  112. (*             S    : AnyStr;                                               *)
  113. (*                                                                          *)
  114. (*          BEGIN                                                           *)
  115. (*                                                                          *)
  116. (*             FillChar( S[1], Dup_Count, Dup_Char );                       *)
  117. (*             S[0] := CHR( Dup_Count );                                    *)
  118. (*                                                                          *)
  119. (*             Dupl := S;                                                   *)
  120. (*                                                                          *)
  121. (*          END;                                                            *)
  122. (*                                                                          *)
  123. (*--------------------------------------------------------------------------*)
  124.  
  125. BEGIN (* Dupl *)
  126.  
  127. INLINE(
  128.   $8A/$4E/$06/           {          MOV       CL,[BP+6]  ; Pick up dup count (0..255)}
  129.   $30/$ED/               {          XOR       CH,CH      ; Clear upper byte of count}
  130.   $C4/$7E/$0A/           {          LES       DI,[BP+10] ; Result address}
  131.   $FC/                   {          CLD                  ; Set direction flag}
  132.   $88/$C8/               {          MOV       AL,CL      ; Get result length}
  133.   $AA/                   {          STOSB                ; Store result length}
  134.   $8B/$46/$08/           {          MOV       AX,[BP+8]  ; Get char to duplicate}
  135.   $F2/$AA);              {          REP       STOSB      ; Perform duplication}
  136.  
  137. END   (* Dupl *);
  138.  
  139. (*----------------------------------------------------------------------*)
  140. (*               Min --- Find minimum of two integers                   *)
  141. (*----------------------------------------------------------------------*)
  142.  
  143. FUNCTION Min( A, B: INTEGER ) : INTEGER;
  144.  
  145. (*----------------------------------------------------------------------*)
  146. (*                                                                      *)
  147. (*   Function: Min                                                      *)
  148. (*                                                                      *)
  149. (*   Purpose:  Returns smaller of two numbers                           *)
  150. (*                                                                      *)
  151. (*   Calling sequence:                                                  *)
  152. (*                                                                      *)
  153. (*      Smaller := MIN( A , B ) : INTEGER;                              *)
  154. (*                                                                      *)
  155. (*         A       --- 1st input integer number                         *)
  156. (*         B       --- 2nd input integer number                         *)
  157. (*         Smaller --- smaller of A, B returned                         *)
  158. (*                                                                      *)
  159. (*                                                                      *)
  160. (*   Calls:  None                                                       *)
  161. (*                                                                      *)
  162. (*                                                                      *)
  163. (*----------------------------------------------------------------------*)
  164.  
  165. BEGIN (* Min *)
  166.  
  167.    IF A < B Then
  168.       Min := A
  169.    Else
  170.       Min := B;
  171.  
  172. END   (* Min *);
  173.  
  174. (*----------------------------------------------------------------------*)
  175. (*               Max --- Find maximum of two integers                   *)
  176. (*----------------------------------------------------------------------*)
  177.  
  178. FUNCTION Max( A, B: INTEGER ) : INTEGER;
  179.  
  180. (*----------------------------------------------------------------------*)
  181. (*                                                                      *)
  182. (*   Function:  Max                                                     *)
  183. (*                                                                      *)
  184. (*   Purpose:  Returns larger of two numbers                            *)
  185. (*                                                                      *)
  186. (*   Calling sequence:                                                  *)
  187. (*                                                                      *)
  188. (*      Larger := MAX( A , B ) : INTEGER;                               *)
  189. (*                                                                      *)
  190. (*         A       --- 1st input integer number                         *)
  191. (*         B       --- 2nd input integer number                         *)
  192. (*         Larger  --- Larger of A, B returned                          *)
  193. (*                                                                      *)
  194. (*                                                                      *)
  195. (*   Calls:  None                                                       *)
  196. (*                                                                      *)
  197. (*----------------------------------------------------------------------*)
  198.  
  199. BEGIN (* Max *)
  200.  
  201.    IF A > B Then
  202.       Max := A
  203.    Else
  204.       Max := B;
  205.  
  206. END   (* Max *);
  207.  
  208. (*--------------------------------------------------------------------------*)
  209. (*               UpperCase --- Convert string to upper case                 *)
  210. (*--------------------------------------------------------------------------*)
  211.  
  212. FUNCTION UpperCase( S: AnyStr ): AnyStr;
  213.  
  214. (*--------------------------------------------------------------------------*)
  215. (*                                                                          *)
  216. (*    Function: UpperCase                                                   *)
  217. (*                                                                          *)
  218. (*    Purpose:  Convert string to upper case                                *)
  219. (*                                                                          *)
  220. (*    Calling Sequence:                                                     *)
  221. (*                                                                          *)
  222. (*       Upper_String := UpperCase( S : AnyStr ): AnyStr;                   *)
  223. (*                                                                          *)
  224. (*          S            --- String to be converted to upper case           *)
  225. (*          Upper_String --- Resultant uppercase string                     *)
  226. (*                                                                          *)
  227. (*    Calls:  UpCase                                                        *)
  228. (*                                                                          *)
  229. (*    Remarks:                                                              *)
  230. (*                                                                          *)
  231. (*       This routine could be coded directly in Turbo as:                  *)
  232. (*                                                                          *)
  233. (*          VAR                                                             *)
  234. (*              I    : INTEGER;                                             *)
  235. (*              L    : INTEGER;                                             *)
  236. (*              T    : AnyStr;                                              *)
  237. (*                                                                          *)
  238. (*          BEGIN                                                           *)
  239. (*                                                                          *)
  240. (*             L := ORD( S[0] );                                            *)
  241. (*                                                                          *)
  242. (*             FOR I := 1 TO L DO                                           *)
  243. (*                T[I] := UpCase( S[I] );                                   *)
  244. (*                                                                          *)
  245. (*             T[0]      := CHR( L );                                       *)
  246. (*             UpperCase := T;                                              *)
  247. (*                                                                          *)
  248. (*         END;                                                             *)
  249. (*                                                                          *)
  250. (*--------------------------------------------------------------------------*)
  251.  
  252. BEGIN (* UpperCase *)
  253.  
  254. INLINE(
  255.   $1E/                   {         PUSH    DS                ; Save DS}
  256.   $C5/$76/$06/           {         LDS     SI,[BP+6]         ; Get source string address}
  257.   $C4/$7E/$0A/           {         LES     DI,[BP+10]        ; Get result string address}
  258.   $FC/                   {         CLD                       ; Forward direction for strings}
  259.   $AC/                   {         LODSB                     ; Get length of source string}
  260.   $AA/                   {         STOSB                     ; Copy to result string}
  261.   $30/$ED/               {         XOR     CH,CH}
  262.   $88/$C1/               {         MOV     CL,AL             ; Move string length to CL}
  263.   $E3/$0E/               {         JCXZ    Exit              ; Skip if null string}
  264.                          {;}
  265.   $AC/                   {UpCase1: LODSB                     ; Get next source character}
  266.   $3C/$61/               {         CMP     AL,'a'            ; Check if lower-case letter}
  267.   $72/$06/               {         JB      UpCase2}
  268.   $3C/$7A/               {         CMP     AL,'z'}
  269.   $77/$02/               {         JA      UpCase2}
  270.   $2C/$20/               {         SUB     AL,'a'-'A'        ; Convert to uppercase}
  271.                          {;}
  272.   $AA/                   {UpCase2: STOSB                     ; Store in result}
  273.   $E2/$F2/               {         LOOP    UpCase1}
  274.                          {;}
  275.   $1F);                  {Exit:    POP     DS                ; Restore DS}
  276.  
  277. END   (* UpperCase *);
  278.  
  279. (*--------------------------------------------------------------------------*)
  280. (*        Adjust_Hour --- Convert 24 hour time to 12 hour am/pm             *)
  281. (*--------------------------------------------------------------------------*)
  282.  
  283. PROCEDURE Adjust_Hour( VAR Hour : WORD;
  284.                        VAR AmPm : STRING2 );
  285.  
  286. (*----------------------------------------------------------------------*)
  287. (*                                                                      *)
  288. (*    Procedure: Adjust_Hour                                            *)
  289. (*                                                                      *)
  290. (*    Purpose:   Converts 24 hour time to 12 hour am/pm time            *)
  291. (*                                                                      *)
  292. (*    Calling sequence:                                                 *)
  293. (*                                                                      *)
  294. (*       Adjust_Hour( VAR Hour : WORD; AmPm : String2 );                *)
  295. (*                                                                      *)
  296. (*          Hour --- Input = Hours in 24 hour form;                     *)
  297. (*                   Output = Hours in 12 hour form.                    *)
  298. (*          AmPm --- Output 'am' or 'pm' indicator                      *)
  299. (*                                                                      *)
  300. (*----------------------------------------------------------------------*)
  301.  
  302. BEGIN (* Adjust_Hour *)
  303.  
  304.    IF ( Hour < 12 ) THEN
  305.       BEGIN
  306.          AmPm := 'am';
  307.          IF ( Hour = 0 ) THEN
  308.             Hour := 12;
  309.       END
  310.    ELSE
  311.       BEGIN
  312.          AmPm := 'pm';
  313.          IF ( Hour <> 12 ) THEN
  314.             Hour := Hour - 12;
  315.       END;
  316.  
  317. END   (* Adjust_Hour *);
  318.  
  319. (*----------------------------------------------------------------------*)
  320. (*   Dir_Convert_Date_And_Time --- Convert directory creation date/time *)
  321. (*----------------------------------------------------------------------*)
  322.  
  323. PROCEDURE Dir_Convert_Date_And_Time(     Time   : LONGINT;
  324.                                      VAR S_Date : AnyStr;
  325.                                      VAR S_Time : AnyStr  );
  326.  
  327. (*----------------------------------------------------------------------*)
  328. (*                                                                      *)
  329. (*     Procedure: Dir_Convert_Date_And_Time                             *)
  330. (*                                                                      *)
  331. (*     Purpose:   Convert creation date/time from DOS directory entry.  *)
  332. (*                                                                      *)
  333. (*     Calling Sequence:                                                *)
  334. (*                                                                      *)
  335. (*        Dir_Convert_Date_And_Time(     Time   : LONGINT;              *)
  336. (*                                   VAR S_Date : AnyStr;               *)
  337. (*                                   VAR S_Time : AnyStr );             *)
  338. (*                                                                      *)
  339. (*           Time   --- Packed time/date as read from DOS directory     *)
  340. (*           S_Date --- converted date in dd-mon-yy format              *)
  341. (*           S_Time --- converted time in hh:mm ampm format             *)
  342. (*                                                                      *)
  343. (*     Calls:                                                           *)
  344. (*                                                                      *)
  345. (*        UnPackTime                                                    *)
  346. (*                                                                      *)
  347. (*----------------------------------------------------------------------*)
  348.  
  349. VAR
  350.    DT   : DateTime;
  351.    YY   : String[2];
  352.    HH   : String[2];
  353.    MM   : String[3];
  354.    DD   : String[2];
  355.    AmPm : STRING[2];
  356.  
  357. BEGIN (* Dir_Convert_Date_And_Time *)
  358.                                    (* If time stamp is 0, don't bother *)
  359.                                    (* to unpack it.                    *)
  360.    IF ( Time = 0 ) THEN
  361.       BEGIN
  362.          S_Date := '         ';
  363.          S_Time := '        ';
  364.       END
  365.    ELSE
  366.       BEGIN
  367.                                    (* Get date/time values *)
  368.          UnpackTime( Time , DT );
  369.  
  370.          WITH DT DO
  371.             BEGIN
  372.  
  373.                STR( ( Year - 1900 ): 2 , YY );
  374.  
  375.                MM := Month_Names[ Month ];
  376.  
  377.                STR( Day:2 , DD );
  378.  
  379.                S_Date := DD + '-' + MM + '-' + YY;
  380.  
  381.                IF ( ( Hour + Min + Sec ) = 0 ) THEN
  382.                   S_Time := '        '
  383.                ELSE
  384.                   BEGIN
  385.  
  386.                      Adjust_Hour( WORD( Hour ) , AmPm );
  387.  
  388.                      STR( Hour:2 , HH );
  389.                      STR( Min: 2 , MM );
  390.  
  391.                      IF ( MM[1] = ' ' ) THEN MM[1] := '0';
  392.  
  393.                      S_Time := HH + ':' + MM + ' ' + AmPm;
  394.  
  395.                   END;
  396.  
  397.             END;
  398.  
  399.       END;
  400.  
  401. END  (* Dir_Convert_Date_And_Time *);
  402.  
  403. (*----------------------------------------------------------------------*)
  404. (*   Dir_Convert_Date_And_Time --- Convert directory creation date/time *)
  405. (*----------------------------------------------------------------------*)
  406.  
  407. PROCEDURE Dir_Convert_Date_And_Time_2(     Time   : LONGINT;
  408.                                        VAR S_Date : AnyStr;
  409.                                        VAR S_Time : AnyStr  );
  410.  
  411. (*----------------------------------------------------------------------*)
  412. (*                                                                      *)
  413. (*     Procedure: Dir_Convert_Date_And_Time_2                           *)
  414. (*                                                                      *)
  415. (*     Purpose:   Convert creation date/time from DOS directory entry.  *)
  416. (*                                                                      *)
  417. (*     Calling Sequence:                                                *)
  418. (*                                                                      *)
  419. (*        Dir_Convert_Date_And_Time_2(     Time   : LONGINT;            *)
  420. (*                                     VAR S_Date : AnyStr;             *)
  421. (*                                     VAR S_Time : AnyStr );           *)
  422. (*                                                                      *)
  423. (*           Time   --- Packed time/date as read from DOS directory     *)
  424. (*           S_Date --- converted date in yy/mm/dd format               *)
  425. (*           S_Time --- converted time in hh:mm 24 hour format          *)
  426. (*                                                                      *)
  427. (*     Calls:                                                           *)
  428. (*                                                                      *)
  429. (*        UnPackTime                                                    *)
  430. (*                                                                      *)
  431. (*----------------------------------------------------------------------*)
  432.  
  433. VAR
  434.    DT   : DateTime;
  435.    YY   : String[2];
  436.    HH   : String[2];
  437.    MM   : String[2];
  438.    DD   : String[2];
  439.  
  440. BEGIN (* Dir_Convert_Date_And_Time_2 *)
  441.  
  442.                                    (* If time stamp is 0, don't bother *)
  443.                                    (* to unpack it.                    *)
  444.    IF ( Time = 0 ) THEN
  445.       BEGIN
  446.          S_Date := '        ';
  447.          S_Time := '     ';
  448.       END
  449.    ELSE
  450.       BEGIN
  451.                                    (* Get date/time values *)
  452.          UnpackTime( Time , DT );
  453.  
  454.          WITH DT DO
  455.             BEGIN
  456.  
  457.                STR( ( Year - 1900 ): 2 , YY );
  458.  
  459.                STR( Month:2 , MM );
  460.  
  461.                IF ( MM[ 1 ] = ' ' ) THEN MM[ 1 ] := '0';
  462.  
  463.                STR( Day:2 , DD );
  464.  
  465.                IF ( DD[ 1 ] = ' ' ) THEN DD[ 1 ] := '0';
  466.  
  467.                S_Date := YY + '/' + MM + '/' + DD;
  468.  
  469.                IF ( ( Hour + Min + Sec ) = 0 ) THEN
  470.                   S_Time := '        '
  471.                ELSE
  472.                   BEGIN
  473.  
  474.                      STR( Hour:2 , HH );
  475.                      STR( Min: 2 , MM );
  476.  
  477.                      IF ( HH[ 1 ] = ' ' ) THEN HH[ 1 ] := '0';
  478.                      IF ( MM[ 1 ] = ' ' ) THEN MM[ 1 ] := '0';
  479.  
  480.                      S_Time := HH + ':' + MM;
  481.  
  482.                   END;
  483.  
  484.             END;
  485.  
  486.       END;
  487.  
  488. END  (* Dir_Convert_Date_And_Time_2 *);
  489.  
  490. (*----------------------------------------------------------------------*)
  491. (*   Convert_String_To_AsciiZ -- Convert Turbo string to Ascii Z String *)
  492. (*----------------------------------------------------------------------*)
  493.  
  494. PROCEDURE Convert_String_To_AsciiZ( VAR S: AnyStr );
  495.  
  496. (*----------------------------------------------------------------------*)
  497. (*                                                                      *)
  498. (*     Procedure:  Convert_String_To_AsciiZ                             *)
  499. (*                                                                      *)
  500. (*     Purpose:    Convert Turbo string to ascii Z string               *)
  501. (*                                                                      *)
  502. (*     Calling Sequence:                                                *)
  503. (*                                                                      *)
  504. (*        Convert_String_To_AsciiZ( VAR S: AnyStr );                    *)
  505. (*                                                                      *)
  506. (*           S --- Turbo string to be turned into Ascii Z string        *)
  507. (*                                                                      *)
  508. (*     Calls:                                                           *)
  509. (*                                                                      *)
  510. (*        None                                                          *)
  511. (*                                                                      *)
  512. (*----------------------------------------------------------------------*)
  513.  
  514. BEGIN (* Convert_String_To_AsciiZ *)
  515.  
  516.    S := S + CHR( 0 );
  517.  
  518. END   (* Convert_String_To_AsciiZ *);
  519.  
  520. (*----------------------------------------------------------------------*)
  521. (*     Dir_Set_Disk_Transfer_Address --- Set DMA address for disk I/O   *)
  522. (*----------------------------------------------------------------------*)
  523.  
  524. PROCEDURE Dir_Set_Disk_Transfer_Address( VAR DMA_Buffer );
  525.  
  526. (*----------------------------------------------------------------------*)
  527. (*                                                                      *)
  528. (*     Procedure:  Dir_Set_Disk_Transfer_Address                        *)
  529. (*                                                                      *)
  530. (*     Purpose:    Sets DMA address for disk transfers                  *)
  531. (*                                                                      *)
  532. (*     Calling Sequence:                                                *)
  533. (*                                                                      *)
  534. (*        Dir_Set_Disk_Transfer_Address( VAR DMA_Buffer );              *)
  535. (*                                                                      *)
  536. (*           DMA_Buffer --- direct memory access buffer                 *)
  537. (*                                                                      *)
  538. (*     Calls:                                                           *)
  539. (*                                                                      *)
  540. (*        MsDos                                                         *)
  541. (*                                                                      *)
  542. (*----------------------------------------------------------------------*)
  543.  
  544. VAR
  545.    Dir_Reg: Registers;
  546.  
  547. BEGIN (* Dir_Set_Disk_Transfer_Address *)
  548.  
  549.    Dir_Reg.Ax := $1A00;
  550.    Dir_Reg.Ds := SEG( DMA_Buffer );
  551.    Dir_Reg.Dx := OFS( DMA_Buffer );
  552.  
  553.    MsDos( Dir_Reg );
  554.  
  555. END   (* Dir_Set_Disk_Transfer_Address *);
  556.  
  557. (*----------------------------------------------------------------------*)
  558. (*     Dir_Get_Volume_Label   ---  Get volume label of a disk           *)
  559. (*----------------------------------------------------------------------*)
  560.  
  561. PROCEDURE Dir_Get_Volume_Label(     Volume       : CHAR;
  562.                                 VAR Volume_Label : AnyStr;
  563.                                 VAR Time         : LONGINT );
  564.  
  565. (*----------------------------------------------------------------------*)
  566. (*                                                                      *)
  567. (*    Procedure: Dir_Get_Volume_Label                                   *)
  568. (*                                                                      *)
  569. (*    Purpose:   Gets volume label for specified disk                   *)
  570. (*                                                                      *)
  571. (*    Calling sequence:                                                 *)
  572. (*                                                                      *)
  573. (*       Dir_Get_Volume_Label(     Volume       : CHAR;                 *)
  574. (*                             VAR Volume_Label : AnyStr;               *)
  575. (*                             VAR Time         : LONGINT );            *)
  576. (*                                                                      *)
  577. (*          Volume       --- Disk letter for which to get label         *)
  578. (*          Volume_Label --- Actual label itself                        *)
  579. (*          Time         --- Packed creation date/time of volume label  *)
  580. (*                                                                      *)
  581. (*    Remarks:                                                          *)
  582. (*                                                                      *)
  583. (*       Because of various bugs in the MS DOS 2.x file searching       *)
  584. (*       facilities, this routine will not return a volume date or time *)
  585. (*       for DOS 2.x.                                                   *)
  586. (*                                                                      *)
  587. (*----------------------------------------------------------------------*)
  588.  
  589. TYPE
  590.    Directory_Record = RECORD
  591.                          Filler    : ARRAY[1..21] Of BYTE;
  592.                          File_Attr : BYTE      (* File attributes *);
  593.                          File_Time : LONGINT   (* Creation time   *);
  594.                          File_Size : LONGINT   (* Size in bytes   *);
  595.                          File_Name : ARRAY[1..80] Of CHAR (* Name *);
  596.                       END;
  597.  
  598.    Extended_FCB    = RECORD
  599.                         Fcb_Flag    : BYTE                 (* $FF = extended FCB *);
  600.                         Filler1     : ARRAY[1..5] OF BYTE;
  601.                         FCB_Attr    : BYTE                 (* File attribute *);
  602.                         FCB_Drive   : BYTE                 (* Drive *) ;
  603.                         FCB_FileName: ARRAY[1..11] OF CHAR (* File name *);
  604.                         FCB_BlockNo : INTEGER              (* Block # *);
  605.                         FCB_RecSize : INTEGER              (* Record size *);
  606.                         FCB_FileSize: Longint              (* File size *);
  607.                         FCB_Date    : INTEGER              (* File date *);
  608.                         FCB_Time    : INTEGER              (* File time *);
  609.                         Filler2     : ARRAY[1..33] OF BYTE (* Make 64 bytes *);
  610.                      END;
  611.  
  612. VAR
  613.    Volume_Data  : Directory_Record;
  614.    Regs         : Registers;
  615.    Volume_Pat   : STRING[15];
  616.    OVolume_Data : Extended_FCB;
  617.    Volume_FCB   : Extended_FCB;
  618.  
  619. BEGIN (* Dir_Get_Volume_Label *)
  620.                                    (* Use FCB code for DOS 2.x *)
  621.  
  622.    IF ( LO( DosVersion ) = 2 ) THEN
  623.       WITH Regs DO
  624.          BEGIN (* Dos 2.x *)
  625.                                    (* Clear out FCBs *)
  626.  
  627.             FillChar( Volume_FCB  , 64, 0 );
  628.             FillChar( OVolume_Data, 64, 0 );
  629.  
  630.                                    (* Set up extended FCB for volume *)
  631.                                    (* label search.                  *)
  632.  
  633.             Volume_FCB.FCB_Flag    := $FF;
  634.             Volume_FCB.FCB_Attr    := VolumeID;
  635.             Volume_FCB.FCB_Drive   := ORD( Volume ) - ORD('A') + 1;
  636.  
  637.             FillChar( Volume_FCB.FCB_FileName, 11, '?' );
  638.  
  639.                                    (* Set address to receive volume label *)
  640.  
  641.             Dir_Set_Disk_Transfer_Address( OVolume_Data );
  642.  
  643.                                    (* Call DOS to search for volume label *)
  644.  
  645.             Regs.Ds := SEG( Volume_FCB );
  646.             Regs.Dx := OFS( Volume_FCB );
  647.             Regs.Ax := $1100;
  648.             MsDos( Regs );
  649.                                    (* Check if we got label.  If so,      *)
  650.                                    (* get it.  Date and time will most    *)
  651.                                    (* likely be garbage, so set them to   *)
  652.                                    (* zero so they won't be listed later. *)
  653.  
  654.             IF ( Regs.Al = $FF ) THEN
  655.                Volume_Label := ''
  656.             ELSE
  657.                Volume_Label := OVolume_Data.FCB_FileName;
  658.  
  659.             Time := 0;
  660.  
  661.          END   (* Dos 2.x *)
  662.    ELSE
  663.       WITH Regs DO
  664.          BEGIN  (* Dos 3.x and higher *)
  665.  
  666.                                    (* Set up DMA address for volume info *)
  667.  
  668.             Dir_Set_Disk_Transfer_Address( Volume_Data );
  669.  
  670.                                    (* Search root directory for label *)
  671.  
  672.             Volume_Pat := Volume + ':*.*';
  673.  
  674.             Convert_String_To_AsciiZ( Volume_Pat );
  675.  
  676.             Regs.Ds := SEG( Volume_Pat[1] );
  677.             Regs.Dx := OFS( Volume_Pat[1] );
  678.             Regs.Ax := $4E00;
  679.             Regs.Cx := VolumeID;
  680.  
  681.                                    (* Find volume label *)
  682.             MsDos( Regs );
  683.  
  684.             IF ( FCarry AND Regs.Flags ) <> 0 THEN
  685.                BEGIN                  (* No volume label found *)
  686.                   Volume_Label := '';
  687.                   Time         := 0;
  688.                END
  689.             ELSE
  690.                WITH Volume_Data DO
  691.                   BEGIN               (* Extract volume label *)
  692.                      Volume_Label := TRIM( COPY( File_Name, 1, POS( #0 , File_Name ) - 1 ) );
  693.                      Time         := File_Time;
  694.                   END;
  695.  
  696.          END (* Dos 3.x and higher *);
  697.  
  698. END   (* Dir_Get_Volume_Label *);
  699.  
  700.